module controller.user;

import std.datetime.systime : Clock;
import std.json : JSONValue;
import std.conv : to, text;
import vibe.http.server : HTTPServerRequest, HTTPServerResponse;
import vibe.data.json : Json, deserializeJson;

import repository.user;
import repository.dept;
import repository.role;
import models.user;
import models.dept;
import dtos.user;
import utils.respdata;
import utils.jwt;
import utils.objmapping;
import utils.cacheutil;

import std.stdio : writeln;

/** 
 * token检查
 */
void checkToken(HTTPServerRequest req, HTTPServerResponse resp)
{
    if ("Authorization" !in req.headers)
    {
        resp.writeJsonBody(RespData.newData(401, "请登录"), 401);
        return;
    }
    string token = req.headers["Authorization"];
    // writeln(token);
    if (!validateToken(token))
    {
        resp.writeJsonBody(RespData.newData(401, "token验证失败"), 401);
        return;
    }

    auto tokenData = decodeToken(token);
    auto exp = tokenData.claims.exp;
    // writeln("token exp:");
    // writeln(exp);
    long now = Clock.currTime.toUnixTime();
    if (exp <= now)
    {
        resp.writeJsonBody(RespData.newData(401, "token已过期"), 401);
        return;
    }

    auto jwtUser = tokenData.claims.getObject("user");
    // writeln(jwtUser);
    if (!jwtUser)
    {
        resp.writeJsonBody(RespData.newData(401, "token不正确"), 401);
        return;
    }

    long userId = jwtUser["userId"].get!long; // 不能用get!string报错
    // writeln(userId);
    // 从缓存中查用户信息
    auto cacheUserDate = cacheData.get(text(userId));
    // writeln(cacheUserDate);
    if (cacheUserDate.isNull)
    {
        resp.writeJsonBody(RespData.newData(401, "token不正确"), 401);
        return;
    }
}

/** 
 * 退出登录
 */
void logout(HTTPServerRequest req, HTTPServerResponse resp)
{
    if ("Authorization" !in req.headers)
    {
        resp.writeJsonBody(RespData.newData(401, "请登录"), 401);
        return;
    }
    string token = req.headers["Authorization"];
    if (!validateToken(token))
    {
        resp.writeJsonBody(RespData.newData(401, "token验证失败"), 401);
        return;
    }

    auto tokenData = decodeToken(token);
    auto exp = tokenData.claims.exp;
    long now = Clock.currTime.toUnixTime();
    if (exp <= now)
    {
        resp.writeJsonBody(RespData.newData(401, "token已过期"), 401);
        return;
    }

    auto jwtUser = tokenData.claims.getObject("user");
    if (!jwtUser)
    {
        resp.writeJsonBody(RespData.newData(401, "token不正确"), 401);
        return;
    }

    long userId = jwtUser["userId"].get!long; // 不能用get!string报错
    // 从缓存中查用户信息
    auto cacheUserDate = cacheData.get(text(userId));
    if (cacheUserDate.isNull)
    {
        resp.writeJsonBody(RespData.newData(401, "token不正确"), 401);
        return;
    }

    cacheData.remove(text(userId));
    cacheData.remove(token);
    resp.writeJsonBody(RespData.newData(200, "ok"));
}

/** 
 * 用户信息
 */
void getMeInfo(HTTPServerRequest req, HTTPServerResponse resp)
{
    import std.algorithm : each;

    if ("Authorization" !in req.headers)
    {
        resp.writeJsonBody(RespData.newData(401, "请登录"), 401);
        return;
    }
    string token = req.headers["Authorization"];

    // 从缓存中查用户id
    auto cacheUserId = cacheData.get(token);
    // writeln(cacheUserDate);
    if (cacheUserId.isNull)
    {
        resp.writeJsonBody(RespData.newData(401, "token不正确"), 401);
        return;
    }
    long userId = to!long(cacheUserId.get);

    // 用户基本信息
    auto user = getUserById(userId);
    JSONValue userInfo = ["nickname": user.nickname, "avatar": user.avatar];
    userInfo.object["userId"] = JSONValue(userId);

    // writeln(user.username);

    // 用户角色信息
    string[] roles;
    user.roles.each!(x => roles ~= x.code);
    // writeln(roles);
    userInfo.object["roles"] = JSONValue(roles);

    // 用户权限信息
    string[] perms;
    // writeln(user.roles[0].menus.length);
    if (user.roles.length > 0 && user.roles[0]!is null && user.roles[0].menus.length > 0)
    {
        user.roles[0].menus.each!((x) {
            if (x.perm == "" || x.perm is null)
            {
                return;
            }
            perms ~= x.perm;
        });
        // writeln(perms);
    }
    // writeln(perms);
    userInfo.object["perms"] = JSONValue(perms);

    resp.writeJsonBody(RespData.newData(200, "ok", userInfo));
}

/** 
 * 用户列表
 */
void getUsers(HTTPServerRequest req, HTTPServerResponse resp)
{
    import std.array : join;
    import std.algorithm : each;
    import vibe.data.json : Json, serializeToJson;

    string deptId = "";
    if ("deptId" in req.query)
    {
        deptId = req.query["deptId"];
    }

    // 放弃处理分页
    auto allUser = getAllUsers();
    // writeln(allUser.length);

    UserDto[] userDtos = [];
    foreach (user; allUser)
    {
        auto userDto = mappingToObject!(UserDto, User)(user);
        userDto.deptName = user.dept.name;
        if (deptId != "" && text(user.dept.id) != deptId)
        {
            continue;
        }

        string[] roleNamesArr;
        user.roles.each!(x => roleNamesArr ~= x.name);
        userDto.roleNames = join(roleNamesArr, ",");

        userDtos ~= userDto;
    }

    Json jsonData = Json.emptyObject;
    jsonData["total"] = allUser.length;
    jsonData["list"] = serializeToJson(userDtos);

    Json data = Json.emptyObject;
    data["code"] = 200;
    data["msg"] = "ok";
    data["data"] = jsonData;

    resp.writeJsonBody(data);
}

/**
* 添加用户
*/
void addUser(HTTPServerRequest req, HTTPServerResponse resp)
{
    import std.datetime.systime : Clock;
    import utils.common;

    // 接收前端数据
    Json json = req.json;
    if (json.length == 0)
    {
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }
    // writeln(json);
    // 反序列化存在问题（数组[]反序列化问题），改用下面方法
    // UserDtoForCreate newUser = deserializeJson!(UserDtoForCreate)(json);

    UserDtoForCreate newUser = new UserDtoForCreate();
    newUser.username = json["username"].get!string;
    newUser.nickname = json["nickname"].get!string;
    newUser.gender = json["gender"].get!int;
    newUser.deptId = json["deptId"].get!long;
    newUser.status = json["status"].get!int;
    if ("mobile" in json)
    {
        newUser.mobile = json["mobile"].get!string;
    }
    if ("email" in json)
    {
        newUser.email = json["email"].get!string;
    }

    long[] roleIds = deserializeJson!(long[])(json["roleIds"]);

    if (newUser.username == "" || newUser.nickname == "" || roleIds.length == 0)
    {
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }

    auto userToAdd = mappingToObject!(User, UserDtoForCreate)(newUser);
    userToAdd.password = toSHA256String("123456");
    userToAdd.avatar = `https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png`;
    userToAdd.dept = getDeptById(newUser.deptId);
    userToAdd.roles = getRolesByIds(roleIds);
    userToAdd.createTime = Clock.currTime().toUnixTime();

    int gender = json["gender"].get!int;
    switch (gender)
    {
    case 0:
        userToAdd.genderLabel = "未知";
        break;
    case 1:
        userToAdd.genderLabel = "男";
        break;
    case 2:
        userToAdd.genderLabel = "女";
        break;
    default:
        userToAdd.genderLabel = "未知";
    }
    bool res = doAddUser(userToAdd);
    if (!res)
    {
        resp.writeJsonBody(RespData.newData(500, "操作失败"), 500);
        return;
    }

    resp.writeJsonBody(RespData.newData(200, "ok"), 200);
}

/**
* 删除用户
*/
void deleteUser(HTTPServerRequest req, HTTPServerResponse resp)
{
    import std.conv : to;
    import std.array : split;
    import std.algorithm : canFind;

    if ("userid" !in req.params)
    {
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }

    string reqUserid = req.params["userid"];
    bool res;
    // 删除单个
    if (!canFind(reqUserid, ","))
    {
        long userid = to!long(reqUserid);
        res = deleteUserById(userid);
    }
    else
    {
        // 批量删除
        string[] tempids = reqUserid.split(",");
        long[] userids;
        foreach (string tempid; tempids)
        {
            userids ~= to!long(tempid);
        }
        res = deleteUserByIds(userids);
    }

    if (!res)
    {
        resp.writeJsonBody(RespData.newData(500, "操作失败"), 500);
        return;
    }
    resp.writeJsonBody(RespData.newData(200, "ok"));
}

/**
* 重置密码
*/
void resetUserPwd(HTTPServerRequest req, HTTPServerResponse resp)
{
    if ("userid" !in req.params)
    {
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }
    // 接收前端数据
    Json json = req.json;
    if (json.length == 0)
    {
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }

    string userid = req.params["userid"];
    bool res = resetPwd(to!long(userid), json["password"].get!string);
    if (!res)
    {
        resp.writeJsonBody(RespData.newData(500, "操作失败"), 500);
        return;
    }
    resp.writeJsonBody(RespData.newData(200, "ok"));
}

void editUserStatus(HTTPServerRequest req, HTTPServerResponse resp)
{
    if ("userid" !in req.params)
    {
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }
    if ("status" !in req.query)
    {
        resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
        return;
    }

    bool res = setUserStatus(to!long(req.params["userid"]), to!int(req.query["status"]));
    if (!res)
    {
        resp.writeJsonBody(RespData.newData(500, "操作失败"), 500);
        return;
    }
    resp.writeJsonBody(RespData.newData(200, "ok"));
}
